package cn.yhp.mybatis.builder;

import cn.yhp.mybatis.mapping.MappedStatement;
import cn.yhp.mybatis.mapping.ResultMap;
import cn.yhp.mybatis.mapping.SqlCommandType;
import cn.yhp.mybatis.mapping.SqlSource;
import cn.yhp.mybatis.scripting.LanguageDriver;
import cn.yhp.mybatis.session.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * 映射构建器助手，建造者
 * @author yhp
 * @date 2023/12/8
 */
public class MapperBuilderAssistant extends BaseBuilder{

    private String currentNamespace;
    private String resource;

    public MapperBuilderAssistant(Configuration configuration,String resource) {
        super(configuration);
        this.resource=resource;
    }

    public String getCurrentNamespace(){
        return currentNamespace;
    }

    public void setCurrentNamespace(String currentNamespace) {
        this.currentNamespace = currentNamespace;
    }

    /**
     * 给标签id赋予命名空间，组成全包名路径
     * @param base
     * @param isReference
     * @return
     */
    public String applyCurrentNamespace(String base,boolean isReference){
        if (base == null){
            return null;
        }
        if (isReference){
            if (base.contains(".")) return base;
        }
        return currentNamespace+"."+base;
    }

    /**
     * 组装映射器语句，并添加到配置对象中
     * @param id
     * @param sqlSource
     * @param sqlCommandType
     * @param parameterType
     * @param resultMap
     * @param returnType
     * @param lang
     * @return
     */
    public MappedStatement addMappedStatement(String id, SqlSource sqlSource, SqlCommandType sqlCommandType,
                                              Class<?> parameterType, String resultMap,
                                              Class<?> returnType, LanguageDriver lang){
        // 给mapper的sql语句id标签加上namespace前缀，如cn.yhp.mybatis.test.dao.IUserDao.queryUserInfoById
        id=applyCurrentNamespace(id,false);
        MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlCommandType, sqlSource, returnType);

        // 结果映射，给 MappedStatement#resultMaps
        setStatementResultMap(resultMap,returnType,statementBuilder);

        MappedStatement statement = statementBuilder.build();
        // 映射语句信息，建造完存放到配置项中
        configuration.addMappedStatement(statement);

        return statement;
    }

    private void setStatementResultMap(String resultMap, Class<?> resultType, MappedStatement.Builder statementBuilder) {
        // 因为暂时还没有在 Mapper XML 中配置 Map 返回结果，所以这里返回的是 null
        resultMap = applyCurrentNamespace(resultMap,true);

        List<ResultMap> resultMaps=new ArrayList<>();
        if (resultMap != null) {
            // TODO：暂无Map结果映射配置，本章节不添加此逻辑
        }
        /*
         * 通常使用 resultType 即可满足大部分场景
         * <select id="queryUserInfoById" resultType="cn.bugstack.mybatis.test.po.User">
         * 使用 resultType 的情况下，Mybatis 会自动创建一个 ResultMap，基于属性名称映射列到 JavaBean 的属性上。
         */
        else if (resultType != null) {
            ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(
                    configuration,
                    statementBuilder.id() + "-Inline",
                    resultType,
                    new ArrayList<>());
            // 将封装的resultMap对象添加集合
            resultMaps.add(inlineResultMapBuilder.build());
        }
        // 并且绑定在MappedStatement映射器对象属性中
        statementBuilder.resultMaps(resultMaps);
    }
}
